package com.jbp.service.impl;

import com.jbp.exception.RRException;
import com.jbp.model.*;
import com.jbp.redis.RedisConfigService;
import com.jbp.service.*;
import com.jbp.service.UserHobbyService;
import com.jbp.service.UserPhotoService;
import com.jbp.service.UserRelationService;
import com.jbp.utils.*;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.jbp.dao.UserDao;
import com.jbp.service.UserService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;


@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);

    @Autowired
    private UserHobbyService userHobbyService;

    @Autowired
    private RedisConfigService redisConfigService;

    @Autowired
    private UserPhotoService userPhotoService;

    @Autowired
    private RoomService roomService;
    @Autowired
    private RoomManagerService roomManagerService;

    @Autowired
    private RoomUserWheatService roomUserWheatService;

    @Autowired
    private UserRelationService userRelationService;

    @Autowired
    private WalletService walletService;

    @Autowired
    private UserBlackService userBlackService;

    @Autowired
    private TecentMsgService tecentMsgService;

    @Autowired
    private PropertyService propertyService;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private SkillUserService skillUserService;

    @Autowired
    private LoginLogService loginLogService;

    @Autowired
    private UserNobilityService userNobilityService;

    @Autowired
    private AccountService accountService;

    @Autowired
    private UserLevelService userLevelService;

    @Autowired
    private EquipUserService equipUserService;

    @Autowired
    private KeywordService keywordService;

    @Override
    public PageUtils queryPage(List<Integer> ids,Integer pg ) {
        Map<String, Object> params=new HashMap<>();
        params.put("page",pg);
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        if (ids == null || ids.size() < 1){
            queryWrapper.eq("id",0);
        }else{
            queryWrapper.in("id",ids);
        }

        IPage<User> page = this.page(
                new Query<User>().getPage(params),
                queryWrapper
        );

        return new PageUtils(page);
    }

/*
    @Transactional
    @Override
    public synchronized R login(User user) {
        User usercheck=this.getOne(new QueryWrapper<User>().eq("mobile",user.getMobile()));
        //记录原记录登录设备
        String device=usercheck == null ? null : usercheck.getDevice();

        //设备锁开启
        if (device!=null && usercheck.getDeviceLock()==1) {
            if (!user.getDevice().equalsIgnoreCase(device)) {
                throw new RRException("设备锁开启，请用原设备登录");
            }
        }

        boolean flag=false; // flag表示用户是否存在，默认认为用户不存在
        if (user.getType().equals("note")){
            //短信登录
            if (StringUtils.isEmpty(user.getMessageCode())){
                return R.error("验证码为空");
            }
            Object obj= redisConfigService.get(Constant.CODE_PREFIX+user.getMobile());
            if (obj == null){
                return R.error("请先发送验证码");
            }
            if (!obj.equals(user.getMessageCode())){
                return R.error("验证码不正确");
            }

            //验证码效验
            if (usercheck == null){
                *//**
                 * 注册
                 *//*
                //生成邀请码
                String code = UUIDUtil.inviteCode();
                while (true) { //确保邀请码唯一
                    if(!isCodeExits(code)) {
                        user.setCode(code);
                        break;
                    } else {
                        code = UUIDUtil.inviteCode();
                    }
                }
                user.setSalt(code);
                *//**
                 * 生成靓号
                 *//*
                String uuid=CreateUUid.createCode();
                while (true) { //确保uuid唯一
                    if(!isUuidExits(uuid)) {
                        user.setUuid(uuid);
                        break;
                    } else {
                        uuid = CreateUUid.createCode();
                    }
                }
                user.setIsOnline("online");
                user.setCreateTime(new Date());
                user.setType("normal");
                String ip = IPReqUtil.getIpAddr(request);
                if (StringUtils.isNotEmpty(ip)) {
                    user.setIp(ip);
                }
                this.save(user);

                // 记录登录日志
                this.createLoginLog(user.getId(), user.getDevice(), ip, "note");

                //生成钱包
                Wallet wallet = new Wallet();
                wallet.setUserId(user.getId());
                walletService.save(wallet);

                tecentMsgService.addUser(user.getId());
            }else{
                flag=true;
            }
        }else{
            if (usercheck == null){
                return  R.error("账号不存在");
            }
            String key = "user:pass:trytimes:"+usercheck.getId();
            int tryTimes = redisConfigService.getInt(key);
            if (tryTimes>=5) {
                return R.error("密码已锁定，请用验证码登录");
            }
            if (!StrToMillsUtil.passwordEncode(user.getPassword(),usercheck.getSalt()).equals(usercheck.getPassword())){
                redisConfigService.set(key, tryTimes+1, 60*60L);
                if(5-tryTimes-1>0) {
                    return R.error("密码错误,再错" + (5 - tryTimes - 1) + "次将锁定1小时");
                } else {
                    return R.error("密码已锁定");
                }
            }
            flag = true;
            *//*UserBlack userBlack= userBlackService.getOne(Wrappers.<UserBlack>lambdaQuery().eq(UserBlack::getUserId,usercheck.getId()).eq(UserBlack::getDevice,user.getDevice()));
            if (userBlack == null && !user.getDevice().equals(device)){
                flag = true;
            }else{
                if (userBlack!=null && userBlack.getType().equals("black")){
                    return R.error("请用验证码登录");
                }
            }*//*

        }
        if (flag){
            usercheck.setDevice(user.getDevice());
            usercheck.setIsOnline("online");
            String ip = IPReqUtil.getIpAddr(request);
            if (StringUtils.isNotEmpty(ip)) {
                usercheck.setIp(ip);
            }
            usercheck.setAesVipara(user.getAesVipara());
            usercheck.setAesKey(user.getAesKey());
            this.updateById(usercheck);

            // 记录登录日志
            this.createLoginLog(usercheck.getId(), user.getDevice(), ip, "password");

            BeanUtils.copyProperties(usercheck,user);
        }
        if (device != null  && !user.getDevice().equals(device)){
            UserBlack userBlack= userBlackService.getOne(Wrappers.<UserBlack>lambdaQuery().eq(UserBlack::getUserId,user.getId()).eq(UserBlack::getDevice,user.getDevice()));
            if (userBlack == null){
                userBlack=new UserBlack();
                userBlack.setCreateTime(new Date());
                userBlack.setUserId(user.getId());
                userBlack.setDevice(device);
                userBlack.setType("black");
                userBlackService.save(userBlack);
            }else{
                if (!userBlack.getType().equals("white")){
                    userBlack.setType("black");
                    userBlack.setCreateTime(new Date());
                    userBlackService.updateById(userBlack);
                }
            }
            userBlack= userBlackService.getOne(Wrappers.<UserBlack>lambdaQuery().eq(UserBlack::getUserId,user.getId()).eq(UserBlack::getDevice,device));
            if (userBlack != null){
                if (!userBlack.getType().equals("white")){
                    userBlack.setType("white");
                    userBlack.setCreateTime(new Date());
                    userBlackService.updateById(userBlack);
                }
            }


        }
        user.setType("normal");
        user.setPassword("");
        user.setSalt("");
        String sessionId=UUIDUtil.creatUUID();
        user.setToken(user.getMobile());
//        String token=UUIDUtil.creatUUID();
//        user.setToken(token);
        user.setSessionId(sessionId);

        redisConfigService.set(user.getMobile(), sessionId);
        *//**
         * 清除验证码缓存
         *//*
        redisConfigService.remove(Constant.CODE_PREFIX+user.getMobile());

        tecentMsgService.addUser(user.getId(), true);
        return R.ok(user);
    }*/

    private void createLoginLog(Integer userId, String device, String ip, String type){
        // 记录登录日志，为避免登录日志记录出现异常，影响正常登录逻辑，所以忽略登录日志记录的异常
        try {
            LoginLog loginLog = new LoginLog();
            loginLog.setLoginTime(new Date());
            loginLog.setUserId(userId);
            loginLog.setDevice(device);
            loginLog.setIp(ip);
            loginLog.setLoginType(type);
            loginLogService.save(loginLog);
        } catch (Exception e) {
            logger.error("记录登录日志失败", e);
        }
    }

    @Override
    public boolean isCodeExits(String code) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("code",code);
        return getOne(queryWrapper) != null;
    }

    @Override
    public boolean isUuidExits(String uuid) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("uuid",uuid);
        return getOne(queryWrapper) != null;
    }

    @Override
    public User modifyInformation(User user) {
        keywordService.checkContent(user.getName());

        user.setName(user.getName().trim());
        User userTemp = this.getById(user.getId());
        if (userTemp == null){
            throw new RRException("当前用户不存在");
        }
        //每天只能修改一次用户名
        if (StringUtils.isNotEmpty(userTemp.getName()) && !user.getName().equals(userTemp.getName()) && userTemp.getLevel()<30 && userTemp.getEditTime()!=null) {
            SimpleDateFormat sf= new SimpleDateFormat("yyyyMMdd");
            /*if (sf.format(new Date()).equals(sf.format(userTemp.getEditTime()))) {
                throw new RRException("请明天再试！");
            }*/
        }
        userTemp.setEditTime(new Date());

        if (!StringUtils.isEmpty(user.getName())){
            User u1 = getOne(new QueryWrapper<User>().eq("name", user.getName()).ne("id", user.getId()));
            if (u1!=null) {
                throw new RRException("用户名已存在");
            }
            userTemp.setName(user.getName());
        }
        if (!StringUtils.isEmpty(user.getCity())){
            userTemp.setCity(user.getCity());
        }
        if (!StringUtils.isEmpty(user.getBirthday())){
            userTemp.setBirthday(user.getBirthday());
        }
        if (!StringUtils.isEmpty(user.getSex())){
            userTemp.setSex(user.getSex());
        }
        if (!StringUtils.isEmpty(user.getHeight())){
            userTemp.setHeight(user.getHeight());
        }
        if (!StringUtils.isEmpty(user.getIndividuality())){
            userTemp.setIndividuality(user.getIndividuality());
        }
        if (!StringUtils.isEmpty(user.getInterest())){
            userTemp.setInterest(user.getInterest());
        }
        if (!StringUtils.isEmpty(user.getIsOnline())){
            userTemp.setIsOnline(user.getIsOnline());
        }
        if (!StringUtils.isEmpty(user.getImg())){
            userTemp.setImg(user.getImg());
        }
        if (!StringUtils.isEmpty(user.getVocation())){
            userTemp.setVocation(user.getVocation());
        }
        if (!StringUtils.isEmpty(user.getVoice())){
            userTemp.setVoice(user.getVoice());
        }
        if (!StringUtils.isEmpty(user.getPassword())){
            if (!RegularExpressionUtil.checkPassword(user.getPassword())){
                throw new RRException("密码规则 8~16位 数字、字母组合");
            }
            String password = StrToMillsUtil.passwordEncode(user.getPassword(), userTemp.getSalt());
            userTemp.setPassword(password);
        }

        if (!StringUtils.isEmpty(user.getInviteCode())){
            //查询上级用户
            User upUser = getOne(new QueryWrapper<User>().eq("code", user.getInviteCode().toUpperCase()));
            if (upUser==null) {
                throw new RRException("邀请码错误");
            }
            userTemp.setUpUserId(upUser.getId());
        }

        //录入信息
        boolean flag = this.updateById(userTemp);
        if (!flag){//返回结果为false  则保存失败
            throw new RRException("信息资料保存失败");
        }
        //资料保存成功 清除重要隐私信息
        userTemp.setPassword("");
        userTemp.setSalt("");

        tecentMsgService.addUser(user.getId());
        return userTemp;
    }

    public static void main(String[] args) {
        System.out.println(StrToMillsUtil.passwordEncode("123456","CYAGXL"));
    }

    @Override
    public User getUserInformation(Integer myUserId, User user) {
        if(!user.getId().equals(myUserId)) {
            user.setMobile("");
        }
        //兴趣爱字符串转换成数组
        if (user.getInterest() !=null) {
            String[] split = user.getInterest().split(",");
            List<String> hobbys = new ArrayList<>();
            if (split.length > 0) {
                for (int i = 0; i < split.length; i++) {
                    UserHobby userHobby = userHobbyService.getById(split[i]);
                    if (userHobby != null){
                        hobbys.add(userHobby.getName());
                    }
                }
                user.setHobbys(hobbys);
            }
        }
        List<UserPhoto> photos=userPhotoService.list(new QueryWrapper<UserPhoto>().eq("user_id",user.getId()));
        if (photos != null){
            user.setPhotos(photos);
        }
        //查询用户是否在房间
        RoomUserWheat wheat=  roomUserWheatService.getOne(new QueryWrapper<RoomUserWheat>().eq("user_id",user.getId()));
        if (wheat != null){
            Room room=roomService.getById(wheat.getRoomId());
            User host =getById(room.getUserId());
            if (host != null){
                room.setImg(host.getImg());
            }

            //设置主持人
            List<RoomUserWheat>  userWheats=roomUserWheatService.list(new QueryWrapper<RoomUserWheat>().eq("room_id",room.getId()).eq("room_wheat",1));
            if (userWheats!=null) {
                userWheats.forEach(userWheat->{
                    User zc = getById(userWheat.getUserId());
                    userWheat.setUserName(zc.getName());
                    userWheat.setUserImg(zc.getImg());
                });
            }
            room.setUserWheats(userWheats);

            user.setRoom(room);
        }
        user.setPassword("");
        user.setSalt("");

        Object object = redisConfigService.get(Constant.ROOM_PREFIX+user.getId());
        if (object == null) {
            user.setIsOnline("offline");
        }

        UserRelation userRelation = userRelationService.getByUserAndFriendId(myUserId, user.getId());
        //用户好友关系
        if (userRelation==null) {
            user.setFriendStatus(0);
            user.setBlack(0);
        } else {
            user.setFriendStatus(userRelation.getStatus());
            user.setBlack(userRelation.getBlack());
        }

        //是否显示抽奖
        user.setShowLuck(user.getLevel()>0 ||
                userLevelService.getExperience(myUserId) >= Integer.parseInt(propertyService.getV("show_luck")));

        //是否是大神
        user.setGod(skillUserService.isGod(user.getId()));

        //是否开代充
        if ("1".equals(propertyService.getV("auto_transfer")) && "no".equals(user.getTransfer())) {
            //是否是签约房主或管理
            Room room = roomService.getOne(new QueryWrapper<Room>().eq("user_id", user.getId()));
            if (room!=null && room.getTypeId()!=7) {
                //房主
                user.setTransfer("yes");
            } else {
                //管理
                List<RoomManager> managers = roomManagerService.list(new QueryWrapper<RoomManager>().eq("user_id", user.getId()));
                if (managers!=null) {
                    for (int i = 0; i < managers.size(); i++) {
                        Room r = roomService.getById(managers.get(i).getRoomId());
                        if(r.getTypeId()!=7) {
                            user.setTransfer("yes");
                            break;
                        }
                    }
                }
            }
        }
        user.setLevelOn(userLevelService.levelOn(user.getId()));
        //'car','head','light','card','decor'
        user.setCar(equipUserService.getEquipByUser("car", user.getId()));
        user.setHead(equipUserService.getEquipByUser("head", user.getId()));
        user.setLight(equipUserService.getEquipByUser("light", user.getId()));
        user.setCard(equipUserService.getEquipByUser("card", user.getId()));
        user.setDecor(equipUserService.getEquipByUser("decor", user.getId()));
        return user;
    }

    @Override
    public PageUtils searchUser(Map<String, Object> params) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        if (params.get("name") != null && !params.get("name").equals("")){
            queryWrapper.like("name",params.get("name")).or().like("uuid",params.get("name"));
        }
        queryWrapper.ne("id", params.get("userId"));
        queryWrapper.orderByDesc("create_time");
        IPage<User> page = this.page(
                new Query<User>().getPage(params),
                queryWrapper
        );
        page.getRecords().forEach(user -> {
            user.setPassword("");
            user.setSalt("");
            user.setMobile("");
            Object object = redisConfigService.get(Constant.ROOM_PREFIX+user.getId());
            if (object == null) {
                user.setIsOnline("offline");
            }

            UserRelation userRelation = userRelationService.getByUserAndFriendId((Integer) params.get("userId"), user.getId());
            if (userRelation==null) {
                user.setFriendStatus(0);
            } else {
                user.setFriendStatus(userRelation.getStatus());
            }
        });
        return new PageUtils(page);
    }

    /**新用户*/
    @Override
    public PageUtils latestUser(Map<String, Object> params) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.ne("id", params.get("userId"));
        queryWrapper.gt("id", 999999999);
        queryWrapper.orderByDesc("create_time");
        IPage<User> page = this.page(
                new Query<User>().getPage(params),
                queryWrapper
        );
        page.getRecords().forEach(user -> {
            user.setPassword("");
            user.setSalt("");
            user.setMobile("");
            Object object = redisConfigService.get(Constant.ROOM_PREFIX+user.getId());
            if (object == null) {
                user.setIsOnline("offline");
            }

            UserRelation userRelation = userRelationService.getByUserAndFriendId((Integer) params.get("userId"), user.getId());
            if (userRelation==null) {
                user.setFriendStatus(0);
            } else {
                user.setFriendStatus(userRelation.getStatus());
            }
        });
        return new PageUtils(page);
    }

    @Override
    public PageUtils recommendUser(Map<String, Object> params) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.ne("id", params.get("userId"));
        queryWrapper.inSql("id", "select user_id from room_user_wheat");
        queryWrapper.orderByDesc("level");
        IPage<User> page = this.page(
                new Query<User>().getPage(params),
                queryWrapper
        );
        page.getRecords().forEach(user -> {
            user.setPassword("");
            user.setSalt("");
            user.setMobile("");
            Object object = redisConfigService.get(Constant.ROOM_PREFIX+user.getId());
            if (object == null) {
                user.setIsOnline("offline");
            }

            UserRelation userRelation = userRelationService.getByUserAndFriendId((Integer) params.get("userId"), user.getId());
            if (userRelation==null) {
                user.setFriendStatus(0);
            } else {
                user.setFriendStatus(userRelation.getStatus());
            }
        });
        return new PageUtils(page);
    }

    /**猜你喜欢*/
    @Override
    public PageUtils youLikeUser(Map<String, Object> params) {
        IPage<User> page = new Query<User>().getPage(params);
        Integer userId = (Integer) params.get("userId");
        List<Integer> ids = getBaseMapper().youLikeUser(page, userId);

        List<User> users = ids.stream().map(id -> getUserInformation(userId, getById(id))).collect(Collectors.toList());
        page.setRecords(users);
        return new PageUtils(page);
    }

    /**指定ip的 盈利次数-亏损次数*/
    @Override
    public int winCount(String ip) {
        String key = "luck:ip:win:count"+ip;
        Integer count = 0;
        if(redisConfigService.exists(key)) {
            count = (Integer)redisConfigService.get(key);
        } else {
            count = getBaseMapper().winCount(ip);
            if (count==null) {
                count = 0;
            }
            redisConfigService.set(key, count, 5L*60);
        }
        return count;
    }

    @Override
    public User getByUuid(String uuid) {
        QueryWrapper<User> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("uuid",uuid);
        return getOne(queryWrapper);
    }

    /**获取人气值权重*/
    @Override
    public int getPeopleMood(Integer userId) {
        User user = getById(userId);
        if (user.getLevel() > 70) {
            return 80;
        } else if (user.getLevel() > 60) {
            return 70;
        } else if (user.getLevel() > 50) {
            return 60;
        } else if (user.getLevel() > 40) {
            return 50;
        } else if (user.getLevel() > 30) {
            return 40;
        } else if (user.getLevel() > 20) {
            return 30;
        } else if (user.getLevel() > 10) {
            return 20;
        } else {
            return 10;
        }
    }

}
